#ifndef __OC_ServerUtil_H__
#define __OC_ServerUtil_H__

#include "ServerDef.h"
#include "OCMain/StringUtil.h"
#include "OCMain/FileUtil.h"
#include "OCMain/Date.h"
#include "OCMain/Log.h"
#include "json/json.h"
#include "yaml-cpp/yaml.h"

namespace OCPP
{
	class _ServerExport ServerUtil
	{
	public:
		static const String AES_Decode(String aesKey, String aseCode, String ivc = "");
		static const String AES_Encode(String aesKey, String password, String ivc = "");

		static const Json::Value jwtDecode(String token);
		static const String jwtEncode(Json::Value& value);

		static const String jsonToString(Json::Value& value, const String indentation = "");

		static const void WaitHours(int n = 1);
		static const void WaitMinutes(int n = 1);
		static const void WaitSeconds(int n = 1);
	};

	inline YAML::Node getYamlNode(const YAML::Node& root, StringVector path)
	{
		YAML::Node node = root;
		for (const auto& name : path)
		{
			node = node[name];
			if (!node.IsDefined())
			{
				throw YAML::Exception(node.Mark(), name + " not found.");
			}
		}

		return node;
	}

	template <typename T>
	T getYaml(YAML::Node node, std::vector<String> pathVec) {

		std::vector<YAML::Node> nodePath;
		nodePath.push_back(node);

		for (auto i = 0; i < pathVec.size(); i++)
		{
			String name = pathVec[i];
			YAML::Node node1 = nodePath.back()[name];
			if (!node1.IsDefined()) {
				String msg = "yaml bad path [";
				for (auto j = 0; j != i; j++)
				{
					msg += pathVec[j] + ":";
				}
				msg += name + "]";
				throw YAML::Exception(node1.Mark(), msg.c_str());
			}
			nodePath.push_back(node1);
		}

		return nodePath.back().as<T>();
	}

	template <typename T>
	inline T getYmlValue(const YAML::Node& node, String key, T def)
	{
		try {
			return node[key].as<T>();
		}
		catch (...) {}
		return def;
	}
}

#endif